package tkM

import (
	"errors"
	"fmt"
	"db2s/Meta"
	"db2s/Store"
	"db2s/arg"
	"db2s/dataManage"
	ea "db2s/encryptionAlgorithm"
	"db2s/global"
	"db2s/go-log/log"
	"db2s/outPut"
	"db2s/parDef"
	"db2s/pubM"
	"db2s/ref"
	mq "db2s/topic-mq"
	"os"
	"reflect"
	"strings"
	"sync"
	"sync/atomic"
	"time"
)

func taskBreakPointF(config GlobalParametersConfig) bool {
	return config.rules.Task.Breakpoint
}

func breakPointFuncMap() map[string]reflect.Value {
	return map[string]reflect.Value{
		"task": reflect.ValueOf(taskBreakPointF),
	}
}

func getBreakPointStatus(config GlobalParametersConfig) bool {
	if funcName, ok := breakPointFuncMap()[config.rules.CheckMode]; ok {
		args := []reflect.Value{
			reflect.ValueOf(config),
		}
		l := funcName.Call(args)
		return l[0].Interface().(bool)
	}
	return false
}

func taskXlsWriterTerminalData(plan *SchedulePlan2) error {
	var (
		event = "[xlsWriterTerminalData]"
	)
	log.MainLog().Debug(fmt.Sprintf("(%d) %v Start writing the execution results of table %v.%v into xls...", plan.Object.ObjectLogSeq, event, plan.Object.Schema, plan.Object.Table))
	plan.XlsTerminal.Data = *plan.TPod
	//newCell.Write(plan.XlsTerminal)
	plan.XlsResult.Data.Task = outPut.TaskResultSheet{
		TextCN: plan.TPod.Task.TextCN, TextCT: plan.TPod.Task.TextCT,
		IndexName: plan.TPod.IndexName, IndexType: plan.TPod.IndexType, CardinalityRate: plan.TPod.CardinalityRate,
		IndexCol:       plan.TPod.IndexCol,
		RateEvaluation: plan.TPod.Task.RateEvaluation, Sum: atomic.LoadInt64(plan.TPod.Task.Sum), DataLength: fmt.Sprintf("%v", plan.TPod.Task.DataSize),
		PartitionsSum: plan.TPod.Task.PSum, PartitionsType: plan.TPod.Task.PType,
		TaskName: plan.TPod.Options,
	}
	plan.XlsResult.Data.Comment = fmt.Sprintf("%v", plan.subTaskInfo.ErrorInfo.Load())
	//newCell.Write(*plan.XlsResult)
	//Store.Insert(Store.Insert(), *plan.XlsResult)
	log.MainLog().Debug(fmt.Sprintf("(%d) %v The execution result of table %v.%v is sent successfully. result is {%v}", plan.Object.ObjectLogSeq, event, plan.Object.Schema, plan.Object.Table, plan.TPod))
	return nil
}
func getXlsWriteTerminalFunc() map[string]reflect.Value {
	return map[string]reflect.Value{
		"task": reflect.ValueOf(taskXlsWriterTerminalData),
	}
}
func xlsWriterTerminalData(plan *SchedulePlan2) any {
	if funcName, ok := getXlsWriteTerminalFunc()[GlobalPConfigs.rules.CheckMode]; ok {
		if funcName.Kind() == reflect.Func {
			args := []reflect.Value{
				reflect.ValueOf(plan),
			}
			s := funcName.Call(args)
			return s[0].Interface()
		}
	}
	return nil
}
func generalSchemaTableMap(Object global.Object) (schemaName, tableName string) {
	if len(Object.MSchema) > 0 && Object.Schema != Object.MSchema {
		schemaName = fmt.Sprintf("\"%v:%v\"", Object.Schema, Object.MSchema)
	} else {
		schemaName = fmt.Sprintf("\"%v\"", Object.Schema)
	}
	if len(Object.MTable) > 0 && Object.Table != Object.MTable {
		tableName = fmt.Sprintf("\"%v:%v\"", Object.Table, Object.MTable)
	} else {
		tableName = fmt.Sprintf("\"%v\"", Object.Table)
	}
	return
}
func generalConfigObjectProperty(subMode string, plan *SchedulePlan2) (tableObjectWrite string) {
	var forceIndex string
	schemaName, tableName := generalSchemaTableMap(plan.Object)
	switch subMode {
	case "sync", "rows":
		if len(plan.TPod.IndexName) > 0 {
			forceIndex = fmt.Sprintf(",forceIndex:\"%v\"", plan.TPod.IndexName)
		}
	}
	tableObjectWrite = fmt.Sprintf("%v {%v{role:\"%v\"%v}}  //Rows Sum = %v\n", schemaName, tableName, plan.Object.Role, forceIndex, atomic.LoadInt64(plan.TPod.Task.Sum))
	return
}
func newXlsObject(baseDir string, config GlobalParametersConfig) {
	xlsFileName := fmt.Sprintf("%v/%v", baseDir, config.result.XlsV.XlsFileName)
	if !strings.Contains(xlsFileName, "/") {
		xlsFileName = fmt.Sprintf("./%v", xlsFileName)
	}
	xlsFile = outPut.NewFileOperations(outPut.Xls{
		FileName:  fmt.Sprintf("./%v.xlsx", xlsFileName),
		SheetName: []string{"terminal", "result", "miss"},
		Mode:      config.rules.CheckMode,
		Enroll:    []any{outPut.WorkSheetTerminal{}, outPut.WorkSheetResult{}, outPut.WorkSheetMiss{}},
		Safety:    config.result.XlsV.XlsSafetySwitch,
	})
}
func initTextData(baseDir string, config GlobalParametersConfig) (err error) {
	textFile = outPut.NewFileOperations(outPut.Tex{
		SheetName: []string{"terminal", "result", "miss"},
		Mode:      config.rules.CheckMode,
		Enroll:    []any{outPut.WorkSheetTerminal{Persistence: baseDir}, outPut.WorkSheetResult{Persistence: baseDir}, outPut.WorkSheetMiss{Persistence: baseDir}},
		Safety:    false,
	})
	if err = textFile.Head(); err != nil {
		log.ErrorLog().Error(fmt.Sprintf("Failed to write the TEXT header title. error is %v", err))
		return
	}
	return
}
func initXlsData(baseDir string, config GlobalParametersConfig) (err error) {
	newXlsObject(baseDir, config)
	if err = xlsFile.Create(); err != nil {
		log.ErrorLog().Error(fmt.Sprintf("Failed to create the XLS file. error is %v", err))
		return
	}
	if err = xlsFile.Head(); err != nil {
		log.ErrorLog().Error(fmt.Sprintf("Failed to write the XLS header title. error is %v", err))
		return
	}
	return
}

func gtConfigFileInit(pp dataManage.DataManage, mode string) (ConfigText []outPut.FileOperations, err error) {
	for _, vv := range pp.GetConfigObjectFile(mode) {
		f := outPut.NewFileOperations(outPut.Tex{FileName: vv, Truncate: true})
		if err = f.Init(); err != nil {
			return
		}
		ConfigText = append(ConfigText, f)
	}
	ff := outPut.NewFileOperations(outPut.Tex{FileName: pp.GetConfigModeFileNames(mode), Truncate: true})
	if err = ff.Init(); err != nil {
		fmt.Println("---------ooooooo:", err)
		return
	}
	//初始化配置文件
	ConfigText = append(ConfigText, ff)
	return
}
func initGtConfigData(pp dataManage.DataManage, mode []string) (err error) {
	var event = "[initGtConfigData]"
	//删除目录
	generalConfigText = make(map[string][]outPut.FileOperations)
	for _, subMode := range mode {
		log.MainLog().Info(fmt.Sprintf("Start initializing the gtConfig Output file"))
		var subModeConfigText []outPut.FileOperations
		if subModeConfigText, err = gtConfigFileInit(pp, subMode); err != nil { //初始化对象目录及对应的mode
			log.ErrorLog().Error(fmt.Sprintf("%v init config file/dir fail,wail exit !!! error info is %v", event, err))
			return
		}
		generalConfigText[subMode] = subModeConfigText
	}
	return
}
func initResultData(baseDir string, config GlobalParametersConfig) (err error) {
	//初始化输出目录result
	if !config.result.GeneralResult {
		log.MainLog().Warn(fmt.Sprintf("If the xls generation parameter is set to false, this step will be skipped."))
		return
	}
	log.MainLog().Info("Start initializing the Result data")
	baseDir = fmt.Sprintf("%v/xls", baseDir)
	if err = dirInit(baseDir); err != nil {
		log.ErrorLog().Error(fmt.Sprintf("The creation of the %v directory failed. error is %v", baseDir, err))
		return
	}
	if initXlsData(baseDir, config) != nil {
		return
	}
	if initTextData(baseDir, config) != nil {
		return
	}
	log.MainLog().Info(fmt.Sprintf("The result data initialization has been completed"))
	return
}
func initOtherResultFile(pp dataManage.DataManage, config GlobalParametersConfig) (result ReadWriteFilePointS, err error) {
	log.MainLog().Info(fmt.Sprintf("Start initializing the breakPoint file"))
	newTextBreakPoint = outPut.NewFileOperations(outPut.Tex{FileName: pp.GetRunFileNames("breakPoint"), Truncate: getBreakPointStatus(config), RSymbol: "\n"})
	if err = newTextBreakPoint.Init(); err != nil {
		log.ErrorLog().Error(fmt.Sprintf("init bar break point file fail. error info is %s", err))
		return
	}
	newTextObjectPoint = outPut.NewFileOperations(outPut.Tex{FileName: config.rules.Task.Object, Truncate: false, RSymbol: "\n"})
	if err = newTextObjectPoint.Init(); err != nil {
		log.ErrorLog().Error(fmt.Sprintf("init bar break point file fail. error info is %s", err))
		return
	}
	log.MainLog().Info(fmt.Sprintf("Start initializing the TTY BAR file"))
	if result.TtyBarFin, err = os.OpenFile(pp.GetRunFileNames("ttyBar"), os.O_TRUNC|os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0664); err != nil {
		log.ErrorLog().Error(fmt.Sprintf("init bar monitor finish file fail. error info is %s", err))
		return
	}
	log.MainLog().Info(fmt.Sprintf("Start initializing the parameterRecord file"))
	if result.ParameterRecord, err = os.OpenFile(pp.GetRunFileNames("parameter"), os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0664); err != nil {
		log.ErrorLog().Error(fmt.Sprintf("init %v file fail. error info is %s", global.ParameterRecord, err))
		return
	}
	log.MainLog().Info(fmt.Sprintf("Start initializing the Terminal Output file"))
	newTextTPod = outPut.NewFileOperations(outPut.Tex{FileName: pp.GetRunFileNames("tPod")})
	if err = newTextTPod.Init(); err != nil {
		return
	}
	return
}
func InitGlobalParametersConfig(l *SchemaInitContextConfig) (result *GlobalParametersConfig) {
	var m = l.GtCheckConfig
	var tl = l.TableList
	return &GlobalParametersConfig{
		repair:      m.SecondaryL.RepairV,
		rules:       m.SecondaryL.RulesV,
		dSns:        m.SecondaryL.DSnsV,
		TableObject: m.SecondaryL.TableObject,
		TableList:   tl,
		argPar:      m.ArgInput,
		structs:     m.SecondaryL.RulesV.Struct,
		result:      m.SecondaryL.ResultV,
	}
}
func InitCloseObject(m arg.ConfigParameter, result *GlobalParametersConfig) {
	//closeObject = quit.GetClose(map[string]any{
	//	"dsn": map[string]any{"name": m.SecondaryL.DSnsV.DestDBName,
	//		"drive": m.SecondaryL.DSnsV.DestDrive,
	//		"jdbc":  m.SecondaryL.DSnsV.DestJdbc,
	//	},
	//}, p.DDB, []*os.File{config.FilePoint.BreakPointFin, config.FilePoint.ActiveDataFin, config.FilePoint.TtyBarFin})
	global.GetIoc().RegisterContext("closeObject", closeObject)
}

// NewSchedulePlanConfig 初始化全局共享变量
func NewSchedulePlanConfig(l *SchemaInitContextConfig) (result *GlobalParametersConfig, err error) {
	var baseDir = fmt.Sprintf("result/end/task_%v", time.Now().Format("2006-01-02T15-04-05"))
	var event = "[NewSchedulePlanConfig]"
	result = InitGlobalParametersConfig(l)
	if result.db, err = pubM.InitDSnsPool(l.GtCheckConfig); err != nil {
		err = ref.ErrAddPrintf(event, err)
		log.ErrorLog().Error(fmt.Sprintf("create db connection fail. error info is {%s}", err))
		return
	}
	pp := dataManage.NewDataManage(l.GtCheckConfig.ArgInput.TaskScheduleCmd.Start.Name, "./result", l.GtCheckConfig.SecondaryL.RulesV.Task.ActiveMode)
	if err = pp.Init(); err != nil {
		log.ErrorLog().Error(fmt.Sprintf("init data manage fail. error info is %s", err))
		return nil, err
	}
	if err = initGtConfigData(pp, l.GtCheckConfig.SecondaryL.RulesV.Task.ActiveMode); err != nil {
		log.ErrorLog().Error(fmt.Sprintf("init gtConfig fail. error info is %s", err))
		return
	}
	if err = initResultData(baseDir, *result); err != nil {
		log.ErrorLog().Error(fmt.Sprintf("init result data fail. error info is %s", err))
		return
	}
	if result.FilePoint, err = initOtherResultFile(pp, *result); err != nil {
		log.ErrorLog().Error(fmt.Sprintf("init other result file fail. error info is %s", err))
		return
	}
	if pubM.UpdateModifyParameterSync(result.db.Target, result.FilePoint.ParameterRecord) != nil {
		log.ErrorLog().Error(fmt.Sprintf("update modify parameter fail. error info is %s", err))
		return
	}
	InitCloseObject(l.GtCheckConfig, result)
	global.GetIoc().RegisterContext("globalConfig", result)
	return
}

// NewSchemaInitConfig 创建执行计划配置参数
func NewSchemaInitConfig() (err error) {
	gobject := &GlobalISObject{}
	global.GetIoc().RegisterContext("isObject", gobject)
	return
}

func fileInputObjectTableRole(s string) (res string, role []string) {
	res = s
	if strings.Contains(s, "{") && strings.Contains(s, "}") {
		start := strings.Index(s, "{")
		end := strings.Index(s, "}")
		res = s[:start]
		for _, v := range strings.Split(strings.TrimSpace(s[start+1:end]), "||") {
			role = append(role, v)
		}
		return
	}
	role = []string{"table"}
	return
}
func fileInputObjectSchemaMap(s string, lowerCase bool) (schema, mSchema string) {
	if strings.Contains(s, ":") {
		schema = strings.TrimSpace(strings.Split(s, ":")[0])
		mSchema = strings.TrimSpace(strings.Split(s, ":")[1])
		if !lowerCase {
			schema = strings.ToUpper(strings.TrimSpace(strings.Split(s, ":")[0]))
			mSchema = strings.ToUpper(strings.TrimSpace(strings.Split(s, ":")[1]))
		}
	} else {
		schema = s
		if !lowerCase {
			schema = strings.ToUpper(s)
		}
	}
	return
}
func activeModeRoleMatch(activeMode []string, role string) bool {
	for _, mode := range activeMode {
		switch mode {
		case "object":
			switch role {
			case "view", "mview", "foreign", "func", "job", "package", "procedure", "seq", "trigger", "type":
				return true
			default:
				return false
			}
		case "sync", "rows", "struct":
			switch role {
			case "table":
				return true
			default:
				return false
			}
		}
	}
	return false
}
func inputObjectSchemaTableSplit(line string) (res []Store.TablesData) {
	var (
		taskDefinition                   = GlobalPConfigs.rules.Task
		activeMode, lowerCase, Delimiter = taskDefinition.ActiveMode, taskDefinition.LowerCase, taskDefinition.Limiter
	)
	var schema, mSchema, table, mTable string
	for k, v := range strings.Split(line, Delimiter) {
		if k == 0 { //schema
			schema, mSchema = fileInputObjectSchemaMap(v, lowerCase)
		} else if k == 1 { //table
			v1, role := fileInputObjectTableRole(v)
			if !activeModeRoleMatch(activeMode, role[0]) {
				continue
			}
			table, mTable = fileInputObjectSchemaMap(v1, lowerCase)
			for _, v2 := range role {
				res = append(res, Store.TablesData{
					Schema: schema, MSchema: mSchema, Table: table, MTable: mTable, Role: v2, TaskName: GlobalPConfigs.argPar.TaskScheduleCmd.Start.Name,
				})

			}
		}
	}
	return
}
func objectRoleMd5Unique(s Store.TablesData) (res bool) {
	h := ea.CheckSum().CheckMd5(fmt.Sprintf("%v:%v,%v:%v", s.Schema, s.MSchema, s.Table, s.MTable))
	if _, g := tableObjectRoleUniqHashMap[h]; g {
		log.MainLog().Warn(fmt.Sprintf("There is a duplication of table object %v:%v.%v:%v in the file content and will be skipped.", s.Schema, s.MSchema, s.Table, s.MTable))
	} else {
		tableObjectRoleUniqHashMap[h]++
	}
	return
}
func getObjectRoleList(re Store.TablesData) (res []Store.TablesData) {
	var (
		objectName []string
		err        error
	)
	if re.Table != "*" && !strings.Contains(re.Table, "%") {
		res = append(res, re)
		return
	}
	r := Meta.NewMeta([]string{GlobalPConfigs.dSns.SrcDBName}, "left", re.Role)
	r.Parameter1 = append(r.Parameter1, parDef.Parameter{Con: GlobalPConfigs.db.Source.GetDB("single"), Object: parDef.Object{Schema: re.Schema, Table: re.Table}})
	if objectName, err = r.GetObjectName(); err != nil {
		return
	}
	for _, v := range objectName {
		res = append(res, Store.TablesData{Schema: re.Schema, Table: v, MSchema: re.MSchema, MTable: v, Role: re.Role})
	}
	return
}
func delimiterRuleIf(line, Delimiter string) bool {
	// 按列分割数据
	if !strings.Contains(line, Delimiter) {
		return true
	}
	return false
}
func commentContinue(s string) bool { // //、# 注释跳过
	if strings.HasPrefix(s, "//") {
		return true
	}
	if strings.HasPrefix(s, "#") {
		return true
	}
	return false
}
func inputObjectSplitSendQuit(event string, _ any) (r any) {
	log.MainLog().Debug(event, "start run input Object Split Send Quit Func.")
	ref.MyWaitDel("objectSplit")
	close(ObjectSplitResult)
	log.MainLog().Debug(event, "input Object Split Send Quit Func(close(ObjectSplitResult)) finishes running.")
	return
}
func objectRolePointQuit(event string, _ any) (r any) {
	log.MainLog().Debug(event, "start run Object Role Point Send Quit Func.")
	ref.MyWaitDel("objectRole")
	close(ObjectFlow)
	log.MainLog().Debug(event, "Object Role Point Send Quit Func(close(ObjectFlow)) finishes running.")
	return
}
func inputObjectSplitPointExec(event string, f any) (r any) {
	var line string
	event = fmt.Sprintf("%v -> inputObjectSplitPointExec ", event)
	log.MainLog().Debug(event, "start run input Object Split Point Exec Func.")
	if f == nil || len(f.([]any)) == 0 {
		return
	}
	_, chanParameter, _ := schemaMetaExecFuncParameterSplit(f.([]any))
	switch chanParameter.(type) {
	case *string:
		line = *chanParameter.(*string)
	}
	log.MainLog().Debug(event, "Received send channel msg data(func input parameter) is ", line)
	for _, re := range inputObjectSchemaTableSplit(line) {
		log.MainLog().Debug(event, fmt.Sprintf("The object data that splits data according to the database name and table name is %v", ref.AnyToJsonString(re)))
		ObjectSplitResult <- re
		log.MainLog().Debug(event, fmt.Sprintf("The object data %v was successfully cut and sent to the channel", ref.AnyToJsonString(re)))
	}
	log.MainLog().Debug(event, "input Object Split Point Exec Func finishes running")
	return
}
func objectRolePointList(event string, f any) (r any) {
	event = "[objectRolePointList]"
	if f == nil || len(f.([]any)) == 0 {
		return
	}
	log.MainLog().Debug(event, "start run Object Role Point List Func.")
	_, chanParameter, _ := schemaMetaExecFuncParameterSplit(f.([]any))
	re := chanParameter.(Store.TablesData)
	log.MainLog().Debug(event, "Received send channel msg data(func input parameter) is ", ref.AnyToJsonString(re))
	for _, oji := range getObjectRoleList(re) {
		ObjectFlow <- oji
		if err := Store.TableWriteData(oji); err != nil {
			log.ErrorLog().Error(event, "Table object %v:%v.%v:%v write failed.", oji.Schema, oji.MSchema, oji.Table, oji.MTable)
		}
		log.MainLog().Info(fmt.Sprintf("%v table object %v:%v.%v:%v read successful.", event, oji.Schema, oji.MSchema, oji.Table, oji.MTable))
	}
	return
}
func inputObjectSplitNoteContinue(event string, f any) (r any) {
	event = fmt.Sprintf("%v -> inputObjectSplitNoteContinue ", event)
	log.MainLog().Debug(event, "start run input Object Split Note Continue Func.")
	_, chanParameter, _ := schemaMetaExecFuncParameterSplit(f.([]any))
	if f == nil || !func() bool {
		valueType := reflect.TypeOf(chanParameter)
		// 判断是否为指针类型
		if valueType.Kind() == reflect.Ptr {
			return valueType.Elem().Kind() == reflect.String
		}
		return false
	}() {
		return true
	}
	log.MainLog().Debug(event, fmt.Sprintf("input Object Split is %v Note symbol is %v Split symbol is %v", *chanParameter.(*string), []string{"//", "#"}, GlobalPConfigs.rules.Task.Limiter))
	if commentContinue(*chanParameter.(*string)) {
		log.MainLog().Debug(event, fmt.Sprintf("input Object Split %v Note Continue", *chanParameter.(*string)))
		return true
	}
	if q := delimiterRuleIf(*chanParameter.(*string), GlobalPConfigs.rules.Task.Limiter); q {
		log.MainLog().Debug(event, fmt.Sprintf("input Object Split %v does not match delimiter %v and will be skipped!!!", *chanParameter.(*string), GlobalPConfigs.rules.Task.Limiter))
		r = q
	} else {
		r = q
	}
	return
}
func objectRoleUniqueContinue(event string, f any) (r any) {
	event = fmt.Sprintf("%v -> objectRoleUniqueContinue ", event)
	log.MainLog().Debug(event, "start run Object Role Unique Continue Func.")
	_, chanParameter, _ := schemaMetaExecFuncParameterSplit(f.([]any))
	if f == nil || !func() bool {
		valueType := reflect.TypeOf(chanParameter)
		// 判断是否为指针类型
		return valueType.Kind() == reflect.Struct
	}() {
		return true
	}
	log.MainLog().Debug(event, fmt.Sprintf("Object Role Unique Parameter Value is %v ", chanParameter.(Store.TablesData)))
	return objectRoleMd5Unique(chanParameter.(Store.TablesData))
}
func inputObjectSplitInit(m any) (send mq.MonitorMsgMq) {
	ref.MyWaitAdd("objectSplit")
	return mq.NewMonitorMsgMq1().SetSendMsg(m.(chan any)).SetNormalQuitFunc(global.EFunc{
		FuncName: inputObjectSplitSendQuit}).SetContinueFunc(global.EFunc{
		FuncName: inputObjectSplitNoteContinue}).SetExecFunc([]global.EFunc{
		{FuncName: inputObjectSplitPointExec}})
}
func objectRoleInfoInit(m any) (objectRoleInfoSend mq.MonitorMsgMq) {
	ref.MyWaitAdd("objectRole")
	var wg sync.WaitGroup
	return mq.NewMonitorMsgMq1().SetSendMsg(m.(chan any)).SetCurryLimit(mq.SendCurryLimit{
		Switch:   true,
		Wg:       &wg,
		CurrySum: make(chan struct{}, GlobalPConfigs.rules.Mtc),
	}).SetNormalQuitFunc(global.EFunc{FuncName: objectRolePointQuit}).SetContinueFunc(global.EFunc{
		FuncName: objectRoleUniqueContinue}).SetExecFunc([]global.EFunc{{FuncName: objectRolePointList}})
}

// ReadObjectFile 按行读取文本内容，并按指定列分割,获取待分析的表清单
func ReadObjectFile() (err error) {
	var fi any
	if fi, err = newTextObjectPoint.Read(); err != nil {
		return
	}
	go func() {
		if err = inputObjectSplitInit(fi).NormalChanSendMsg("ReadObjectFile"); err != nil {
			return
		}
	}()
	go func() {
		if err = objectRoleInfoInit(ObjectSplitResult).NormalChanSendMsg("tableRoleInit"); err != nil {
			return
		}
	}()
	return
}
func newTableAttributes(v1 Store.TablesData) (result arg.InputTableAttributes) {
	var status int64 = 1
	return arg.InputTableAttributes{
		Schema: v1.Schema, Table: v1.Table,
		MSchema: func() string {
			if len(v1.MSchema) == 0 {
				return v1.Schema
			}
			return v1.MSchema
		}(),
		MTable: func() string {
			if len(v1.MTable) == 0 {
				return v1.Table
			}
			return v1.MTable
		}(),
		TableJoin: "left", TableStatus: &status, TableAttributes: arg.TableSubOptions{Role: v1.Role},
	}
}
func getTableObject(v1 Store.TablesData) (result arg.InputTableAttributes, err error) {
	var exist bool
	result = newTableAttributes(v1)
	r := Meta.NewMeta([]string{GlobalPConfigs.dSns.SrcDBName}, "left", v1.Role)
	r.Parameter1 = append(r.Parameter1, parDef.Parameter{Con: GlobalPConfigs.db.Source.GetDB("single"), Object: parDef.Object{Schema: v1.Schema, Table: v1.Table}})
	if exist, err = r.GetObjectExistence(); err != nil || exist {
		return
	}
	if err = Store.TableWriteData(Store.MissTableData{
		MissTable: true,
		TablesData: Store.TablesData{
			Id:       v1.Id,
			MSchema:  v1.MSchema,
			MTable:   v1.MTable,
			Role:     v1.Role,
			Schema:   v1.Schema,
			Table:    v1.Table,
			TaskName: v1.TaskName,
		},
	}); err != nil {
		return
	}
	atomic.SwapInt64(result.TableStatus, -1)
	cc := global.GetIoc().GetBean("globalConfig").(*GlobalParametersConfig)
	if cc.FilePoint.ObjectMiss != nil {
		if _, err = cc.FilePoint.ObjectMiss.WriteString(fmt.Sprintf("%v.%v\n", v1.Schema, v1.Table)); err != nil {
			return arg.InputTableAttributes{}, err
		}
	}
	return
}
func initSchemaBean(config *SchemaInitContextConfig) (err error) {
	var event = "[initSchemaBean]"
	//注册输入配置
	global.GetIoc().RegisterContext("configParameter", config.GtCheckConfig)
	defer func() {
		if err != nil {
			log.ErrorLog().Error(fmt.Sprintf("%v init plan Config fail. error is {%v}", event, err))
		}
	}()
	//初始化全局共享配置 	//注册执行计划配置 SchedulePlanConfig
	if GlobalPConfigs, err = NewSchedulePlanConfig(config); err != nil {
		return
	}
	if GlobalPConfigs == nil {
		return errors.New(fmt.Sprintf("GlobalPConfigs is nil."))
	}
	return
}
func objectExistPointQuit(event string, _ any) (r any) {
	ref.MyWaitDel("objectExist")
	close(meta.TableObjectFlow)
	//log.MainLog().Info(fmt.Sprintf("%v When the breakpoint resume function is enabled, table set %v will be skipped.", "getBreakPointTableList", continueTableList))
	return
}
func objectExistPointInit(event string, f any) (r any) {
	var err error
	if f == nil || len(f.([]any)) == 0 {
		return
	}
	_, chanParameter, _ := schemaMetaExecFuncParameterSplit(f.([]any))
	re := chanParameter.(Store.TablesData)
	var q arg.InputTableAttributes
	if q, err = getTableObject(re); err != nil {
		log.ErrorLog().Error(event, fmt.Sprintf("getTableObject error is %v", err))
	}
	meta.TableObjectFlow <- q
	return
}
func objectExistInit(m any) mq.MonitorMsgMq {
	ref.MyWaitAdd("objectExist")
	var wg sync.WaitGroup
	return mq.NewMonitorMsgMq1().SetSendMsg(m.(chan any)).SetCurryLimit(mq.SendCurryLimit{
		Switch:   true,
		Wg:       &wg,
		CurrySum: make(chan struct{}, GlobalPConfigs.rules.Mtc),
	}).SetNormalQuitFunc(global.EFunc{FuncName: objectExistPointQuit}).SetExecFunc([]global.EFunc{{FuncName: objectExistPointInit}})
}

// 初始化上下文，该模块的全局配置，过滤表名，按照join、left、unIo方式
func schemaContext(config *SchemaInitContextConfig) *CheckSchemaMetaData {
	var (
		event = "[schemaContext]"
		err   error
	)
	lock.Lock()
	defer lock.Unlock()
	meta = GetCheckSchemaMetaData()
	if err = initSchemaBean(config); err != nil {
		fmt.Println("创建执行计划上下文 NewSchedulePlanContext 失败", err)
		close(meta.TableObjectFlow)
		return nil
	}
	fmt.Println(fmt.Sprintf("-- [%v] %v report: init config file/dir of %v mode -- ", time.Now().Format("2006-01-02 15:04:05"), arg.ToolName, config.GtCheckConfig.SecondaryL.RulesV.CheckMode))
	log.MainLog().Info(fmt.Sprintf("%v begin init config file/dir of %v mode ", event, config.GtCheckConfig.SecondaryL.RulesV.CheckMode))
	if ReadObjectFile() != nil {
		fmt.Println(fmt.Sprintf("-- [%v] %v report: read table object file fail of %v mode, Please check the log information -- ", time.Now().Format("2006-01-02 15:04:05"), arg.ToolName, config.GtCheckConfig.SecondaryL.RulesV.CheckMode))
		close(meta.TableObjectFlow)
		return nil
	}
	fmt.Println(fmt.Sprintf("-- [%v] %v report: begin init table object group -- ", time.Now().Format("2006-01-02 15:04:05"), arg.ToolName))
	log.MainLog().Info(fmt.Sprintf("%v Start checking whether the group table object exists", event))
	go func() {
		if err = objectExistInit(ObjectFlow).NormalChanSendMsg(event); err != nil {
			log.ErrorLog().Error(event, fmt.Sprintf("objectExistInit error is %v", err))
			return
		}
	}()
	return meta
}
